/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/* $Id: kf701.h 35 2007-07-10 05:51:12Z kf701.ye $ */

#ifndef _KF701_LIB_H_
#define _KF701_LIB_H_

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>

/******************************************
	1.	macro part
*******************************************/
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)>(b)?(b):(a))
#endif

#ifndef CLAMP
#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#endif

#define POINTER_TO_UINT(p)  ((unsigned int)(p))

#if defined (__GNUC__)
#define likely(x)	__builtin_expect(!!(x), 1)
#define unlikely(x)	__builtin_expect(!!(x), 0)
#else
#define likely(x)	(x)
#define unlikely(x)	(x)
#endif

/******************************************
	2.	network part
*******************************************/
int connect_nonblock(char *ip,uint16_t port,uint32_t timeout); 
int open_listenfd(uint16_t port); 
int open_udp(uint16_t port); 

bool setup_route(char *gatewap_ip);
bool delete_route(char *gatewap_ip);
void display_route(void);

void setnonblocking(int fd);

/* unix socket */
int unix_socket_new(void);
void unix_socket_free(int sockfd);
int32_t unix_socket_send(int sockfd , const char *to_path, const char *data, uint32_t size);
int unix_socket_new_listen(const char *unix_path);

/* send email */
typedef struct{
	char *smtp;
	char *passwd;
	char *from;
	char **to;
	uint32_t  numto;
	char *context;
	char *subject;
#define EMAIL_CHARSET	"utf-8"
#define EMAIL_MAXLINE	128
#define EMAIL_MIME	"MIME-Version: 1.0"
#define EMAIL_BOUNDARY	"---kf701libofmailsend---"
} mail_t;
bool send_mail(mail_t *mail);

/* network server */
typedef void (*tcp_data_func)(int, uint8_t*, uint32_t);
void tcp_server_epoll( uint16_t port, uint32_t psize, tcp_data_func func);
void tcp_server_select( uint16_t port, uint32_t psize, tcp_data_func func);

typedef void (*tcp_fd_func)(int);
void tcp_server_select_2( uint16_t port, tcp_fd_func func);

typedef void(*udp_data_func)(struct sockaddr*, uint8_t*, uint32_t);
void udp_server(uint16_t port, uint32_t psize, udp_data_func func);

typedef void(*un_data_func)(const char*, uint8_t*, uint32_t);
void unix_socket_server( const char *unix_path, uint32_t psize, un_data_func func);

/******************************************
	3.	algorithm part
*******************************************/
uint8_t reverse_char(uint8_t);

int32_t encode_b64(uint8_t *dest,const uint8_t *src,uint32_t size);
int32_t decode_b64(uint8_t *desc,const uint8_t *src,uint32_t size);
int32_t b64_file_to_buf (uint8_t *b64_buf, const char *file);

void bin2hex(uint8_t *dest,const uint8_t *src, uint32_t len);
void hex2bin(uint8_t *dest,const uint8_t *src, uint32_t len);

void string_encrypt(uint8_t *dest, const uint8_t *src, const uint8_t *key);
void string_decrypt(uint8_t *dest, const uint8_t *src, const uint8_t *key);

uint8_t *MD5_string (uint8_t *string, uint32_t len);
uint8_t *MD5_file(char *filename);


/******************************************
	4.	tty control part
*******************************************/
bool set_parity(int fd,int32_t databits,int32_t stopbits,int32_t parity);
bool set_speed(int fd, int32_t speed);



/******************************************
	5.	log and debug
*******************************************/
int debug_verbose;
int sys_message(const char *fmt, ...);
#define sys_debug(args...)			\
	do{                    			\
		if (debug_verbose >=4)		\
			sys_message(args);	\
	} while(0)

#define sys_log(args...)			\
	do{                    			\
		if (debug_verbose >=3)		\
			sys_message(args);	\
	} while(0)

#define sys_warn(args...)			\
	do{                       		\
		if (debug_verbose >= 2)		\
			sys_message(args);	\
	} while(0)	

#define sys_err(args...)			\
	do{                       		\
		if (debug_verbose >= 1)		\
			sys_message(args);	\
	} while(0)	



/******************************************
	6.	robust io
*******************************************/
int32_t rio_read(int fd, void * buf, uint32_t size);
int32_t rio_write(int fd, void * buf, uint32_t size);
int32_t readline2(int fd, void *buf, uint32_t size);


/******************************************
	7.	thread part
*******************************************/
typedef void * (*thread_entry_func)(void *);
bool create_normal_thread(thread_entry_func th_func, void *data);
bool create_rr_thread(thread_entry_func th_func, void *data);



/******************************************
	8.	file util part
*******************************************/
bool pad_file(char *filein, char *fileout, uint32_t align_size);
char *iconv_string (const char *str, const char *from_codeset,
		const char *to_codeset);


/******************************************
	9.	rand util	
*******************************************/
int32_t rand_int32_area(int32_t min, int32_t max);
uint32_t rand_int32_from_str(const char *str);
char *rand_ip(char *buffer, uint32_t size);
uint8_t rand_digit(void);
uint8_t rand_alpha_lower(void);
uint8_t rand_alpha_upper(void);
uint8_t *rand_string(uint8_t *buf, uint32_t size);
uint8_t *rand_bytes(uint8_t *buf, uint32_t size);


/******************************************
	10.	draw math util
*******************************************/
typedef struct{
	int32_t x;
	int32_t y;
	int32_t z;
} point_t;

typedef struct{
	uint8_t r;
	uint8_t g;
	uint8_t b;
	uint8_t a;
} color_t;

typedef void (*draw_dot_func)(point_t, color_t);

void draw_line(point_t p1, point_t p2, color_t color, draw_dot_func func);
void draw_polygon(uint32_t num, point_t *array, color_t color, draw_dot_func func);
void draw_triangle(point_t p1, point_t p2, point_t p3, color_t color, draw_dot_func func);
void draw_circle(point_t center, uint32_t radius, color_t color, draw_dot_func func);
void draw_parabola_x(point_t center, int32_t a, color_t color, draw_dot_func func);
void draw_parabola_y(point_t center, int32_t a, color_t color, draw_dot_func func);


/******************************************
	11.	memory pool util
*******************************************/
typedef struct{
	void *addr;
	bool use;
} _mem_slice_t;

typedef struct{
	_mem_slice_t *slice_array;
	uint32_t slice_size;
	uint32_t slice_count;
	uint32_t used_count;
} mem_pool_t;

mem_pool_t *mem_pool_create (uint32_t slice_size, uint32_t pre_count);
void mem_pool_destory (mem_pool_t *pool);

void *mem_pool_malloc (mem_pool_t *pool);
void *mem_pool_malloc0 (mem_pool_t *pool);
void mem_pool_free (mem_pool_t *pool, void *mem);

void mem_pool_debug(mem_pool_t *pool);

/******************************************
	12.	data queue
*******************************************/
typedef struct _node_{
	void *data;
	struct _node_ *next;
	struct _node_ *prev;
} _node_t;

typedef struct{
	_node_t *head;
	_node_t *tail;
	uint32_t length;
} queue_t;

queue_t *data_queue_new(void);
void data_queue_free(queue_t *qu);

uint32_t data_queue_length(queue_t *qu);

void data_queue_push_head(queue_t *qu, void *data);
void data_queue_push_tail(queue_t *qu, void *data);
void data_queue_push_nth(queue_t *qu, void *data, uint32_t n);

void *data_queue_pop_head(queue_t *qu);
void *data_queue_pop_tail(queue_t *qu);
void *data_queue_pop_nth(queue_t *qu, uint32_t n);

void *data_queue_peek_head(queue_t *qu);
void *data_queue_peek_tail(queue_t *qu);
void *data_queue_peek_nth(queue_t *qu, uint32_t n);


/******************************************
	13.	time misc
*******************************************/
/* When ntp is running,the func be useful than time() */
time_t get_uptime(void);


/******************************************
	14.	ps misc
*******************************************/
pid_t pidof( const char *pname );



#endif
